package utils

import (
	"fmt"
	"github.com/lonng/nano"
	"github.com/lonng/nano/component"
	"github.com/lonng/nano/pipeline"
	"github.com/lonng/nano/scheduler"
	"github.com/lonng/nano/session"
	"nano_chatRoom/proto"
	"time"
)

const (
	testRoomID = 1
	roomIDKey = "ROOM_ID"
)
type Room struct {
	Group *nano.Group
}



type State struct {
	component.Base
	Timer         *scheduler.Timer
	OutboundBytes int
	InboundBytes  int
}


func (sts *State)Outbound(s *session.Session, msg *pipeline.Message)error{
	sts.OutboundBytes += len(msg.Data)
	return nil
}

func (sts *State)InBound(s *session.Session, msg *pipeline.Message)error{
	sts.InboundBytes += len(msg.Data)
	return nil
}

//	AfterInit component lifetime callback.
func (sts *State)AfterInit(){
	sts.Timer = scheduler.NewTimer(time.Minute, func() {
		println("OutboundBytes", sts.OutboundBytes)
		println("InboundBytes", sts.InboundBytes)
	})
}


//	RoomManager represents a component that contains a bundle of room.
type RoomManager struct {
	component.Base
	timer *scheduler.Timer
	rooms map[int32]*Room
}

//	NewRoomManager Create a new pointer.
func NewRoomManager()*RoomManager{
	return &RoomManager{
		rooms: map[int32]*Room{},
	}
}

//	Join Room
func (rm *RoomManager) Join(s *session.Session, msg []byte)error{
	//NOTE: join test room only in demo
	room, found := rm.rooms[testRoomID]
	if !found {
		room = &Room{
			Group:nano.NewGroup(fmt.Sprintf("room-%d", testRoomID)),
		}
		rm.rooms[testRoomID] = room
	}
	fakeUID := s.ID() // just use s.ID as uid !!!
	s.Bind(fakeUID)
	s.Set(roomIDKey, room)
	s.Push("onMembers", &proto.AllMembers{Members:room.Group.Members()})
	// notify others
	room.Group.Add(s) //add session to group
	return s.Response(&proto.JoinResponse{Result:"success"})
}

//	Message sync last message to all members
func (rm *RoomManager) Message(s * session.Session, msg *proto.UserMessage)error{
	if !s.HasKey(roomIDKey){
		return fmt.Errorf("not join room yet")
	}
	room := s.Value(roomIDKey).(*Room)
	return room.Group.Broadcast("onMessage",msg)
}

